

#pragma once
#include <string>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>

using namespace std;
enum{SOCKERRO = 2};
static const int gnum = 1024;
class udpClient{
public:
    udpClient(const std::string serverip,const uint16_t serverport) :_serverip(serverip),_serverport(serverport)
    {}

    void initClient(){
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd == -1){
            std::cerr<<"socket fild:"<<errno<<strerror(errno)<<std::endl;
            exit(SOCKERRO);
        }
        //客户端无需bind，os在后续会帮我们自动分配端口号bind
    }
    static void* readinfo(void* args){
       while(true){
            int sockfd = *static_cast<int*>(args);
            pthread_detach(pthread_self());
            sockaddr_in server_info_from;
            socklen_t len = sizeof server_info_from;
            char bufferfrom[gnum];
            ssize_t r = recvfrom(sockfd,bufferfrom,sizeof(bufferfrom)-1,0,(sockaddr*)&server_info_from,&len);
            if(r >  0)  bufferfrom[r]=0;

            cout<<bufferfrom<<endl;
       }
    }

    void start(){
        pthread_create(&_pt,nullptr,readinfo,&_sockfd);
        while(true){
            char buffer[gnum];
            std::cout<<"#";
            fgets(buffer,sizeof buffer,stdin);
            sockaddr_in server_info;
            bzero(&server_info,sizeof server_info);
            server_info.sin_family = AF_INET;
            server_info.sin_addr.s_addr = inet_addr(_serverip.c_str());
            server_info.sin_port = htons(_serverport);

            ssize_t s = sendto(_sockfd,buffer,strlen(buffer),0,(sockaddr*)&server_info,sizeof server_info);
        }
    }

    ~udpClient(){}

private:
    std::string _serverip;
    uint16_t _serverport;
    int _sockfd;
    pthread_t _pt;
};
